package com.kurt.service.impl;

import com.kurt.dto.SysConfigDTO;
import com.kurt.dto.create.SysConfigCreateRequest;
import com.kurt.dto.query.SysConfigQueryRequest;
import com.kurt.dto.update.SysConfigUpdateRequest;
import com.kurt.entity.SysConfig;
import com.kurt.repository.SysConfigRepository;
import com.kurt.service.SysConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 系统配置服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysConfigServiceImpl extends BaseServiceImpl<SysConfig, Long> implements SysConfigService {

    private final SysConfigRepository configRepository;

    @Override
    protected SysConfigRepository getRepository() {
        return configRepository;
    }

    @Override
    protected SysConfigRepository getSpecificationExecutor() {
        return configRepository;
    }

    @Override
    @Transactional
    public SysConfigDTO createConfig(SysConfigCreateRequest createRequest) {
        log.info("创建系统配置: {}", createRequest.getConfigKey());

        // 检查配置键名是否已存在
        if (configRepository.existsByConfigKey(createRequest.getConfigKey())) {
            throw new RuntimeException("配置键名已存在");
        }

        // 创建配置实体
        SysConfig config = new SysConfig();
        BeanUtils.copyProperties(createRequest, config);
        config.setCreateTime(LocalDateTime.now());
        config.setUpdateTime(LocalDateTime.now());
        config.setCreateUserId(com.kurt.util.UserContext.getUserId());
        config.setUpdateUserId(com.kurt.util.UserContext.getUserId());

        // 保存配置
        config = configRepository.save(config);

        log.info("系统配置创建成功: {}", config.getConfigKey());
        return convertToSysConfigDTO(config);
    }

    @Override
    @Transactional
    public SysConfigDTO updateConfig(SysConfigUpdateRequest updateRequest) {
        log.info("更新系统配置: {}", updateRequest.getId());

        // 查找配置
        SysConfig config = getById(updateRequest.getId());

        // 检查配置键名是否已存在（排除自己）
        if (!updateRequest.getConfigKey().equals(config.getConfigKey()) &&
                configRepository.existsByConfigKeyAndIdNot(updateRequest.getConfigKey(), updateRequest.getId())) {
            throw new RuntimeException("配置键名已存在");
        }

        // 更新配置信息
        BeanUtils.copyProperties(updateRequest, config, "id", "createTime", "createUserId");
        config.setUpdateTime(LocalDateTime.now());
        config.setUpdateUserId(com.kurt.util.UserContext.getUserId());

        // 保存配置
        config = configRepository.save(config);

        log.info("系统配置更新成功: {}", config.getConfigKey());
        return convertToSysConfigDTO(config);
    }

    @Override
    public Page<SysConfigDTO> getConfigPage(SysConfigQueryRequest queryRequest) {
        // 构建分页参数
        Sort sort = Sort.by(Sort.Direction.fromString(queryRequest.getOrderDirection()), queryRequest.getOrderBy());
        Pageable pageable = PageRequest.of(queryRequest.getPageNum() - 1, queryRequest.getPageSize(), sort);

        // 构建查询条件
        Specification<SysConfig> spec = buildConfigSpecification(queryRequest);

        // 执行分页查询
        Page<SysConfig> configPage = configRepository.findAll(spec, pageable);

        // 转换为DTO
        return configPage.map(this::convertToSysConfigDTO);
    }

    @Override
    public List<SysConfigDTO> getConfigList(SysConfigQueryRequest queryRequest) {
        // 构建查询条件
        Specification<SysConfig> spec = buildConfigSpecification(queryRequest);

        // 执行查询
        List<SysConfig> configs = configRepository.findAll(spec);

        // 转换为DTO
        return configs.stream().map(this::convertToSysConfigDTO).collect(Collectors.toList());
    }

    @Override
    public String getConfigValue(String configKey) {
        Optional<SysConfig> configOpt = configRepository.findByConfigKey(configKey);
        return configOpt.map(SysConfig::getConfigValue).orElse(null);
    }

    @Override
    public String getConfigValue(String configKey, String defaultValue) {
        String value = getConfigValue(configKey);
        return value != null ? value : defaultValue;
    }

    @Override
    public SysConfigDTO getConfigByKey(String configKey) {
        Optional<SysConfig> configOpt = configRepository.findByConfigKey(configKey);
        return configOpt.map(this::convertToSysConfigDTO).orElse(null);
    }

    @Override
    public boolean existsByConfigKey(String configKey) {
        return configRepository.existsByConfigKey(configKey);
    }

    @Override
    public boolean existsByConfigKeyAndIdNot(String configKey, Long excludeId) {
        return configRepository.existsByConfigKeyAndIdNot(configKey, excludeId);
    }

    @Override
    @Transactional
    public boolean deleteConfigs(List<Long> ids) {
        log.info("批量删除系统配置: {}", ids);

        for (Long id : ids) {
            configRepository.deleteById(id);
        }

        log.info("批量删除系统配置成功: {}", ids);
        return true;
    }

    /**
     * 构建系统配置查询条件
     */
    private Specification<SysConfig> buildConfigSpecification(SysConfigQueryRequest queryRequest) {
        return (root, query, cb) -> {
            List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();

            // 配置名称模糊查询
            if (StringUtils.hasText(queryRequest.getConfigName())) {
                predicates.add(cb.like(root.get("configName"), "%" + queryRequest.getConfigName() + "%"));
            }

            // 配置键名模糊查询
            if (StringUtils.hasText(queryRequest.getConfigKey())) {
                predicates.add(cb.like(root.get("configKey"), "%" + queryRequest.getConfigKey() + "%"));
            }

            // 配置类型查询
            if (StringUtils.hasText(queryRequest.getConfigType())) {
                predicates.add(cb.equal(root.get("configType"), queryRequest.getConfigType()));
            }

            // 状态查询
            if (queryRequest.getStatus() != null) {
                predicates.add(cb.equal(root.get("status"), queryRequest.getStatus()));
            }

            // 创建时间范围查询
            if (StringUtils.hasText(queryRequest.getCreateTimeStart())) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeStart())));
            }
            if (StringUtils.hasText(queryRequest.getCreateTimeEnd())) {
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeEnd())));
            }

            return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
        };
    }

    /**
     * 转换系统配置实体为DTO
     */
    private SysConfigDTO convertToSysConfigDTO(SysConfig config) {
        SysConfigDTO dto = new SysConfigDTO();
        BeanUtils.copyProperties(config, dto);

        // 设置状态文本
        if (config.getStatus() != null) {
            dto.setStatusText(config.getStatus() == 1 ? "启用" : "禁用");
        }

        return dto;
    }
}
